
package stcu;

import com.nvlled.route.*;
import stcu.robjects.*;
import java.util.*;
import java.net.SocketAddress;

public class ServerAuth implements Pinger.Listener {

    private ObjectRouter router;
    //private Set<Account> db;
    private Map<String, Account> db;
    private Set<String> session;
    private DefaultGroup defaultGroup;
    private static final Account account = 
        new Account("0000", "Miranda", "Chito");

    public ServerAuth(ObjectRouter router) {
        this.router = router;
        db = new HashMap<String, Account>();
        session = new HashSet<String>();
        subscribe();
    }

    public Account getAccount() {
        return account;
    }

    public Set<String> getLoggedUsers() {
        return new HashSet<String>(session);
    }

    public void registerUser(Account account) {
        db.put(account.getIDNumber(), account);
    }

    public void setDatabase(Collection<Account> accounts) {
        for (Account account: accounts) {
            db.put(account.getIDNumber(), account);
            //this.db = new HashSet<Account>(db);
        }
    }

    public boolean isLoggedIn(String id) {
        return session.contains(id);
    }

    public void setDefaultGroup(DefaultGroup group) {
        defaultGroup = group;
    }

    public void nodeDown(String name, SocketAddress address) {
        endSession(name);
        String gid = DefaultGroup.DEFAULT_ID+"";
        defaultGroup.receive(new GroupLeave(name, gid));
    }

    private void subscribe() {
        router.subscribe(Login.class, new ObjectReceiver<Login>() {
            public void receive(Login login) {
                String id = login.getIDNumber();
				
                if (db.containsKey(id)) {
                    if (session.contains(id)) {
                        router.deliver(new Login.Status(Login.LOGGED_IN), 
                            login.getSourceAddress());
                    } else {
                        Account account = db.get(id);
                        router.deliver(new Login.Status(Login.OK, account), 
                            login.getSourceAddress());

                        AddressTable table = router.getTable();
                        table.store(id, login.getSourceAddress());
                        session.add(id);
                        System.out.println("logged in " + id);
                    }
                } else {
                    router.deliver(new Login.Status(Login.INVALID_USER), 
                        login.getSourceAddress());
                }
            }
        });
        router.subscribe(Logout.class, new ObjectReceiver<Logout>() {
            public void receive(Logout logout) {
                AddressTable table = router.getTable();
                String id = table.getName(logout.getSourceAddress());
                endSession(id);
            }
        });
    }

    public void endSession(String name) {
        if (session.contains(name)) {
            System.out.println("logged out" + name);
            session.remove(name);
            if (defaultGroup != null) {
                defaultGroup.deleteAuthoredGroups(name);
            }
        }
    }
}

